/* Class in Js*/
//  JavaScript uses functions as classes，自定义对象
function makePerson(first, last) {
    return {
        first: first,
        last: last,
        fullName: function() {
            return this.first + ' ' + this.last;
        },
        fullNameReversed: function() {
            return this.last + ', ' + this.first;
        }
    }
}
s = makePerson("Simon", "Willison");  // funcion return a object
s.fullName(); // Simon Willison
s.fullNameReversed(); // Willison, Simon

// just use this as a funcion object 构造函数
function Person(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = function() {
        return this.first + ' ' + this.last;
    }
    this.fullNameReversed = function() {
        return this.last + ', ' + this.first;
    }
}
// keyword new will create an empty object, the object will call func, and func return this  
var s = new Person("Tim", "Elen"); 


// seperate inner funcion
function personFullName() {
    return this.first + ' ' + this.last;
}
function personFullNameReversed() {
    return this.last + ', ' + this.first;
}
function Person(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = personFullName;
    this.fullNameReversed = personFullNameReversed;
}

// Person.prototype是一个可以被Person的所有实例共享的对象 原型链的一部分
function Person(first, last) {
    this.first = first;
    this.last = last;
}
// 当你试图访问Person没有定义的属性时，解释器会先检查Person.prototype来判断是否存在这样一个属性
Person.prototype.fullName = function() {
    return this.first + ' ' + this.last;
}
// 任何分配给Person.prototype的东西对通过this对象构造的实例都是可用的
Person.prototype.fullNameReversed = function() {
    return this.last + ', ' + this.first;
} 

/* Js允许你在程序中的任何时候修改原型prototype中的一些东西，
也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法 */
s = new Person("Simon", "Willison");
s.firstNameCaps();  // TypeError on line 1: s.firstNameCaps is not a function

// 同样可以给JavaScript的内置函数原型prototype添加东西
Person.prototype.firstNameCaps = function() {
    return this.first.toUpperCase()
}
s.firstNameCaps(); // SIMON

// 原型链的根节点是 Object.prototype
var s = "Simon";
s.reversed(); // TypeError on line 1: s.reversed is not a function

String.prototype.reversed = function() {
    var r = "";
    for (var i = this.length - 1; i >= 0; i--) {
        r += this[i];
    }
    return r;
}
s.reversed(); // nomiS

// apply call
function trivialNew(constructor, ...args) {
    var o = {}; // 创建一个对象
    constructor.apply(o, args);
    return o;
}
// var bill = new Person("William", "Orange");
var bill = trivialNew(Person, "William", "Orange");

// 事件处理 -> 被调用时，将关联的元素变成蓝色
// 当函数被用作事件处理函数时，它的this指向触发事件的元素
function bluify(e){
  console.log(this === e.currentTarget); // 总是 true

  // 当 currentTarget 和 target 是同一个对象时为 true
  console.log(this === e.target);        
  this.style.backgroundColor = '#A5D9F3';
}

// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');

// 将bluify作为元素的点击监听函数，当元素被点击时，就会变成蓝色
for (var i=0 ; i<elements.length ; i++) {
  elements[i].addEventListener('click', bluify, false);
}

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(length) {
    super(length, length);
    this.name = 'Square';
  }
}
// super关键字用于访问和调用一个对象的父对象上的函数。


